/*
    定义构造函数 创建 放大镜的实例化对象

    参数1   放大镜的标签对象
    参数2   放大镜的数据数组

*/

class setGlass {
    constructor(element, imgArr) {
        // 用 属性 存储 形参的实参数据
        this.ele = element;
        this.arr = imgArr;
        // 使用 属性 存储 全局变量
        this.show;
        this.showImg;
        this.mask;
        this.list;
        this.ulLiImgs;
        this.glass;
    }

    // 定义一个入口函数 调用所有需要执行的函数程序
    init() {
        this.setPage();
        this.inoutShow();
        this.inList();
        this.moveShow();
    }

    // 1, 动态生成页面
    setPage() {
        // 创建显示区 div标签
        this.show = document.createElement('div');
        // DOM操作 定义 class
        this.show.classList.add('show');

        // 创建图片标签 设定图片标签src属性
        this.showImg = document.createElement('img');
        // 设定src属性值 默认是数组中第一个单元存储的图片路径
        this.showImg.setAttribute('src', `./images/${this.arr[0].large}`);

        // 创建遮盖层标签 设定class
        this.mask = document.createElement('div');
        this.mask.classList.add('mask');

        // 放大区 背景图片 默认是 数组中第一个单元的图片
        this.glass = document.createElement('div');
        this.glass.classList.add('glass');
        this.glass.style.backgroundImage = `url('./images/${this.arr[0].large}')`;

        // 创建 列表区 ul 定义class
        this.list = document.createElement('ul');
        this.list.classList.add('list');

        // 定义变量 存储 生成的li>img
        let liStr = '';
        this.arr.forEach((item, key) => {
            // item 是 数组中数据单元存储的数据数值 也就是 对象
            // key 是 对象的索引下标

            liStr += key === 0 ? `<li><img name="listImg" class="active" index="${key}" src="./images/${item.small}" alt=""></li>` : `<li><img name="listImg" index="${key}" src="./images/${item.small}" alt=""></li>`;
        });


        // 图片 遮盖层 标签对象 写入 show标签
        this.show.appendChild(this.showImg);
        this.show.appendChild(this.mask);

        // li>img字符串 写入 ul,list标签
        this.list.innerHTML = liStr;

        // 显示区 列表区 放大区 写入 div标签
        this.ele.appendChild(this.show);
        this.ele.appendChild(this.list);
        this.ele.appendChild(this.glass);

        // 获取所有的 ul>li>img 标签
        this.ulLiImgs = this.list.querySelectorAll('img');
    }

    // 2, 鼠标移入移出显示区
    inoutShow() {
        // 显示区 动态生成之后 不会再次动态生成 
        // 可以给 显示区标签 直接 添加事件
        this.show.addEventListener('mouseenter', () => {
            // 让 遮盖层 放大区 显示
            this.mask.style.display = 'block';
            this.glass.style.display = 'block';
        })

        this.show.addEventListener('mouseleave', () => {
            // 让 遮盖层 放大区 消失
            this.mask.style.display = 'none';
            this.glass.style.display = 'none';
        })
    }

    // 3, 鼠标移入列表区
    inList() {
        // 给 所有 图片标签 添加 鼠标移入事件
        // this.ulLiImgs.forEach( ( item , key )=>{
        //     // item 是 img标签对象
        //     // key 是 当前 img标签对象的索引下标

        //     // 给 每一个 img标签 添加 鼠标移入事件
        //     item.addEventListener( 'mouseenter' , ()=>{
        //         // 给所有的 ul>li>img 标签 清除 class,active
        //         this.ulLiImgs.forEach( i => {
        //             i.classList.remove('active');
        //         })

        //         // 给触发事件的图片标签 也就是 item
        //         // 添加 class,active
        //         item.classList.add('active');

        //         // 设定 显示区 img标签 src属性
        //         // 图片标签的索引下标 在 数组中对应的对象单元
        //         this.showImg.setAttribute('src' , `./images/${this.arr[key].large}`);
        //         this.glass.style.backgroundImage = `url('./images/${this.arr[key].large}')`;
        //     })
        // })


        // 给父级 div 添加事件 通过 事件委托 实现
        // 必须要使用 mouseover 事件类型
        this.ele.addEventListener('mouseover', (event) => {
            // 如果触发事件的事件对象是 ul>li>img 标签
            if (event.target.getAttribute('name') === 'listImg') {
                // 清除所有 ul>li>img标签的 class,active
                this.ulLiImgs.forEach(item => {
                    item.classList.remove('active');
                })

                // 给触发事件的事件对象 添加 class,active
                event.target.classList.add('active');

                // 图片标签的索引下标 在 数组中对应的对象单元
                this.showImg.setAttribute('src' , `./images/${this.arr[ Number( event.target.getAttribute('index') ) ].large}`);
                this.glass.style.backgroundImage = `url('./images/${this.arr[ Number( event.target.getAttribute('index') ) ].large}')`;
            }
        })
    }

    // 4, 鼠标在显示区移动
    moveShow() {
        // 直接给 显示区 添加 事件
        this.show.addEventListener('mousemove', (event) => {
            // 外边距
            let oDivLeft = this.ele.offsetLeft;
            let oDivTop = this.ele.offsetTop;

            // 边框线
            let borderLeft = this.show.clientLeft;
            let borderTop = this.show.clientTop;

            // 遮盖层占位 内容+padding+border
            let maskWidth = this.mask.offsetWidth;
            let maskHeight = this.mask.offsetHeight;

            // 显示区占位 内容+padding
            let showWidth = this.show.clientWidth;
            let showHeight = this.show.clientHeight;

            // page定位 - 外边距 - 边框线 - 遮盖层占位一半
            let x = event.pageX - oDivLeft - borderLeft - maskWidth / 2;
            let y = event.pageY - oDivTop - borderTop - maskHeight / 2;

            // 计算极值
            // 最小值   0 
            // 最大值   show占位(内容+padding) - mask占位(内容+padding+border);
            x = x < 0 ? 0 : x;
            y = y < 0 ? 0 : y;

            x = x > showWidth - maskWidth ? showWidth - maskWidth : x;
            y = y > showHeight - maskHeight ? showHeight - maskHeight : y;

            // 将计算的数值 赋值给 遮盖成的定位数值
            // 拼接px单位
            this.mask.style.left = x + 'px';
            this.mask.style.top = y + 'px';

            // 设定背景图片的定位
            // 反向相反 数值是4倍
            this.glass.style.backgroundPosition = `-${x * 4}px -${y * 4}px`;
        })
    }
}